﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using thinger.AutomaticStoreMotionControlLib;
using thinger.AutomaticStoreMotionDAL;
using thinger.AutomaticStoreMotionDAL.Scale;
using thinger.AutomaticStoreMotionDAL.Scanner;
using thinger.AutomaticStoreMotionDAL.Service;
using thinger.AutomaticStoreMotionModels;

namespace thinger.AutomaticStoreMotionPro
{
    public partial class FrmMain : Form
    {
        #region 构造函数
        public FrmMain()
        {
            InitializeComponent();

            this.Load += FrmMain_Load;
        }
        #endregion

        #region 属性和对象
        //创建运动控制单例模式对象
        private GTSMotionEx _gTSMotionEx = GTSMotionEx.GetInstance();

        //创建扫码枪对象
        private Scanner _scanner = new Scanner();

        //创建称重对象
        private Scale _scale = new Scale();

        //添加日志委托
        private Action<int, string> AddLog;

        //添加报警委托
        private Action<string, bool> AddAlarm;

        //添加更新状态委托
        private Action SetRowState;

        //设置批号委托
        private Action<string> SetSNCode;

        //设置条形码委托
        private Action<string> SetCode;

        //设置重量委托
        private Action<string> SetWeight;

        //设置实时位置委托
        private Action<string> SetPos;

        //获取扫码委托
        private Action<string> ScannerRec;

        //线程取消令牌对象
        private CancellationTokenSource _cts;

        //存料边沿触发
        private bool _storeCache = false;

        //取料边沿触发
        private bool _reclaimCache = false;

        //当前存料数量
        private int StoreAvailableCount { get { return ActualStoreDataService.GetAvailableCount(); } }

        //条形码
        private string _currentCode;

        public string CurrentCode
        {
            get { return _currentCode; }
            set
            {
                _currentCode = value;
                SetCode?.Invoke(value);
            }
        }

        //条形码
        private string _currentSNCode;

        public string CurrentSNCode
        {
            get { return _currentSNCode; }
            set
            {
                _currentSNCode = value;
                SetSNCode?.Invoke(value);
            }
        }
        #endregion

        #region 窗口加载
        private void FrmMain_Load(object sender, EventArgs e)
        {
            //Navi按钮事件绑定
            NaviButtonBind();

            //打开默认窗体，实时监控
            naviButton_ClickEvent(this.naviMonitor, null);

            //初始化板卡
            var result = _gTSMotionEx.InitCard();

            if (!result.IsSuccess)
            {
                AddLog.Invoke(2, "板卡初始化失败" + result.ErrorMsg);
            }
            else
            {
                AddLog.Invoke(0, "板卡初始化成功");
            }

            //扫码枪连接
            result = _scanner.Connect(_gTSMotionEx.BasicParam);

            if (!result.IsSuccess)
            {
                AddLog.Invoke(2, "扫码枪连接失败" + result.ErrorMsg);
            }
            else
            {
                _scanner.SannerReceived += _scanner_SannerReceived;
                AddLog.Invoke(0, "扫码枪连接成功");
            }

            //称重连接
            result = _scale.Connect(_gTSMotionEx.BasicParam);

            if (!result.IsSuccess)
            {
                AddLog.Invoke(2, "称重连接失败" + result.ErrorMsg);
            }
            else
            {
                AddLog.Invoke(0, "称重连接成功");
            }

            //监控界面行列数据加载
            SetRowState.Invoke();

            //加载主程序
            _cts = new CancellationTokenSource();
            Task mainTask = new Task(MainProcess, _cts.Token);
            mainTask.Start();
        }

        //界面切换按钮事件绑定
        private void NaviButtonBind()
        {
            foreach (var item in this.topPanel.Controls)
            {
                if (item is NaviButton naviButton)
                {
                    if (naviButton.Name != "naviExit")
                    {
                        naviButton.ClickEvent += naviButton_ClickEvent;
                    }
                }
            }
        }

        //扫码枪数据接收事件
        private void _scanner_SannerReceived(object sender, EventArgs e)
        {
            if (e is SannerReceivedEventArgs scannerMsg)
            {
                if (ScannerRec != null)
                {
                    ScannerRec.Invoke(scannerMsg.Message);
                }
            }
        }
        #endregion

        //*************界面操作相关事件触发**************
        #region 无边框移动
        private Point _point;
        private void mainPanel_MouseDown(object sender, MouseEventArgs e)
        {
            _point = new Point(e.X, e.Y);
        }

        private void mainPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Location = new Point(this.Location.X + e.X - _point.X, this.Location.Y + e.Y - _point.Y);
            }
        }
        #endregion

        #region 窗口切换
        //界面切换按钮事件
        private void naviButton_ClickEvent(object sender, EventArgs e)
        {
            if (sender is NaviButton navi)
            {
                FormNames formNames = FormNames.实时监控;
                if (Enum.TryParse(navi.NaviName, out formNames))
                {
                    OpenWindow(formNames);

                    foreach (var item in this.topPanel.Controls)
                    {
                        if (item is NaviButton navi1)
                        {
                            navi1.IsActive = false;
                        }
                    }

                    navi.IsActive = true;
                }

            }
        }
        //根据输入的窗口名称去切换子面板上的窗口
        private void OpenWindow(FormNames formNames)
        {
            bool isFind = false;
            int ctCount = this.mainPanel.Controls.Count;
            int closedCount = 0;
            for (int i = 0; i < ctCount; i++)
            {
                if (mainPanel.Controls[i - closedCount] is Form frm)
                {
                    //如果是我们需要的
                    if (frm.Text == formNames.ToString())
                    {
                        frm.BringToFront();
                        isFind = true;
                    }
                    //如果不是我们需要的，但是不能关闭的
                    else if (IsFixedForm(frm.Text))
                    {
                        frm.SendToBack();
                    }
                    //其他的
                    else
                    {
                        frm.Close();               // frm.close()动作会减少mainPanel.controls的数量，改变索引的顺序，因此采用关闭计数的方法解决索引问题
                        closedCount++;
                    }
                }
            }

            if (!isFind)
            {
                Form frm = null;
                switch (formNames)
                {
                    case FormNames.实时监控:
                        frm = new FrmMonitor();
                        AddLog = ((FrmMonitor)frm).AddLog;
                        AddAlarm = ((FrmMonitor)frm).AddAlarm;
                        SetRowState = ((FrmMonitor)frm).SetRowState;
                        SetSNCode = ((FrmMonitor)frm).SetSNCode;
                        SetCode = ((FrmMonitor)frm).SetCode;
                        SetWeight = ((FrmMonitor)frm).SetWeight;
                        SetPos = ((FrmMonitor)frm).SetPos;
                        break;
                    case FormNames.手动操作:
                        frm = new FrmManual();
                        break;
                    case FormNames.报警记录:
                        frm = new FrmSysLog();
                        break;
                    case FormNames.历史数据:
                        frm = new FrmHistoryData();
                        break;
                    case FormNames.参数设置:
                        frm = new FrmParameters();
                        break;
                    case FormNames.用户管理:
                        frm = new FrmUserManange();
                        break;
                    default:
                        break;
                }

                frm.TopLevel = false;
                frm.FormBorderStyle = FormBorderStyle.None;
                frm.Dock = DockStyle.Fill;
                frm.Parent = this.mainPanel;
                frm.BringToFront();
                frm.Show();
            }
        }
        //判断是否需要保留的子面板
        private bool IsFixedForm(string formNames)
        {
            //获取所有的固定
            var list = Enum.GetNames(typeof(FormNames)).Where(new Func<string, bool>((string c) => { return (int)Enum.Parse(typeof(FormNames), c, true) < 10; })).ToList();
            return list.Contains(formNames);
        }
        //退出系统按钮事件
        private void naviExit_ClickEvent(object sender, EventArgs e)
        {
            DialogResult result = new FrmConfirm("系统退出", "确认退出系统？", "确认", "取消").ShowDialog();
            if (result == DialogResult.OK)
            {
                _scanner.DisConnect();
                _scale.DisConnection();
                Application.Exit();
            }
        }

        #endregion

        //***********自动流程**************
        private void MainProcess()
        {
            OperationResult result;
            while (_cts.IsCancellationRequested)
            {
                //判断手自动模式
                if (_gTSMotionEx.GetModeState())
                {
                    //检测存料按钮按下
                    if (CheckEdgeSingal(_gTSMotionEx.GetStoreButton(), ref _storeCache))
                    {
                        result = _gTSMotionEx.SetStoreState(true);
                        if (!result.IsSuccess)
                        {
                            AddLog(1, "存料指示灯打开失败");
                            continue;
                        }
                    }

                    AddLog(0, "开始存料流程");
                    //判断存料是否超限
                    if (StoreAvailableCount > _gTSMotionEx.BasicParam.nudAllowInCount)
                    {
                        new FrmConfirmSingleButton("存料流程", "当前存料数量已超限，无法存料！").ShowDialog();
                        AddLog(1, "位置已满，无法存料");

                        result = _gTSMotionEx.SetStoreState(false);
                        if (!result.IsSuccess)
                        {
                            AddLog(1, "存料指示灯关闭失败");
                        }
                        continue;
                    }
                    else
                    {
                        FrmCode frmCode = new FrmCode();
                        this.ScannerRec = frmCode.ScannerRec;
                        DialogResult res = frmCode.ShowDialog();
                        if (res == DialogResult.OK)
                        {
                            //获取当前条码
                            this.CurrentCode = frmCode.code;
                            //提示
                            AddLog(0, "获取条形码：" + this.CurrentCode);

                            //通过条码查找批号
                            string sNCode = ActualStoreDataService.GetSNCodeByCode(this.CurrentCode);
                            if (sNCode.Length > 0)
                            {
                                new FrmConfirmSingleButton("存料异常", "当前条行码已存在，无法存料！").ShowDialog();
                                AddLog(1, "存料终止：当前条行码已存在，对应批号：" + sNCode);

                                result = _gTSMotionEx.SetStoreState(false);
                                if (!result.IsSuccess)
                                {
                                    AddLog(1, "存料指示灯关闭失败");
                                }
                                continue;
                            }

                            //查找出入库
                            sNCode = InOutStoreDataService.GetSNCodeByCode(this.CurrentCode);
                            //确认是否第一次入库
                            bool isFristInStore = sNCode.Length == 0;

                            //如果是第一次入库，弹出批号扫描窗体
                            if (isFristInStore)
                            {
                                FrmSNCode frmSNCode = new FrmSNCode();
                                this.ScannerRec = frmSNCode.ScannerRec;
                                res = frmCode.ShowDialog();
                                if (res == DialogResult.OK)
                                {
                                    this.CurrentSNCode = frmSNCode.code;

                                    //提示：获取批号
                                    AddLog(0, "获取批号：" + this.CurrentSNCode);
                                }
                                else
                                {
                                    //用户取消
                                }
                            }
                            else
                            {

                            }


                        }
                        else
                        {
                            //用户取消
                        }
                    }


                }
                else //如果是手动模式
                {
                    Thread.Sleep(10);
                }
            }
        }

        private bool CheckEdgeSingal(bool current, ref bool cache, bool isRiseOrFall = true)
        {
            if (isRiseOrFall)
            {
                if (current && !cache)
                {
                    cache = current;
                    return true;
                }
                else
                {
                    cache = current;
                    return false;
                }
            }
            else
            {
                if (!current && cache)
                {
                    cache = current;
                    return true;
                }
                else
                {
                    cache = current;
                    return false;
                }
            }
        }


    }

    #region 枚举
    //窗口名的枚举
    public enum FormNames
    {
        实时监控,
        手动操作 = 10, //小于10的窗口，在窗口切换时不能关闭
        报警记录,
        历史数据,
        参数设置,
        用户管理,
        退出系统,
    }
    #endregion
}
